﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Text;

namespace ImageReJoin
{
    class ImageProcess
    {
        mainForm myForm;
        //图像路径
        string image_path;
        //拼接顺序字符串，逗号间隔
        string order_string;
        //是否备份原图
        bool is_backup;
        delegate void SetTextCallback(string status,int amount);//设置委托

        public ImageProcess(mainForm _myForm,string _image_path,string _order_string,bool _is_backup)
        {
            myForm = _myForm;
            image_path = _image_path;
            order_string = _order_string;
            is_backup=_is_backup;
        }
        //重新拼接
        public void reJoinImage()
        {

            string order = order_string;
            string[] image_order = order.Split(',');

            string[] files = Directory.GetFiles(image_path, "*.jpg", SearchOption.AllDirectories);
            //处理总数
            int total_amount = files.Length;
            //处理完成计数
            int done_amount = 0;
            setWorkStatus("正在处理", 0);
            foreach (string file in files)
            {
                Bitmap bmpSource = new Bitmap(file);
                int amount = image_order.Length;
                int total_height = bmpSource.Height;
                int total_width = bmpSource.Width;
                double per_height = total_height * 1.0 / amount;
                Bitmap[] imageArray = new Bitmap[amount];
                //把图片截取出来。
                for (int i = 0; i < amount; i++)
                {
                    int x = 0;
                    int y = (int)per_height * i;
                    //截取的方框
                    Rectangle clipRect = new Rectangle(x, y, total_width, (int)per_height);
                    imageArray[i] = bmpSource.Clone(clipRect, bmpSource.PixelFormat);
                }
                Bitmap bmpTarget = new Bitmap(total_width, total_height);
                Graphics graph = Graphics.FromImage(bmpTarget);
                //初始化这个大图
                graph.DrawImage(bmpTarget, total_width, total_height);
                //初始化当前宽
                int currentHeight = 0;
                for (int i = 0; i < amount; i++)
                {
                    Image image = imageArray[int.Parse(image_order[i])];
                    //拼图
                    graph.DrawImage(image, 0, currentHeight);
                    //拼接改图后，当前高度
                    currentHeight += image.Height;
                }
               
                bmpSource.Dispose();
                string[] f= file.Split('|');
                clearOrBackup(is_backup,f);
                //设置保存的格式
                var eps = new EncoderParameters(1);
                var ep = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, 75L);
                eps.Param[0] = ep;
                var jpsEncodeer = GetEncoder(ImageFormat.Jpeg);
                bmpTarget.Save(file, jpsEncodeer, eps);
                done_amount++;
                setWorkStatus("完成:"+done_amount+"/"+total_amount, (int)(done_amount * 100 / total_amount));
            }
        }
        
        //合成一个大图
        public void Merge()
        {
            string[] files = Directory.GetFiles(image_path, "*.jpg", SearchOption.AllDirectories);
            //处理总数
            int total_amount = files.Length;
            int width = 0;
            int total_height = 0;
            int mergeCount = 0;//合并图片的计数
            const int MAX_HEIGHT = 65500; //最大能够保存的图片像素值
            Bitmap[] imageArray = new Bitmap[total_amount];
            setWorkStatus("开始读取", 0);
            int first= 0;
            int last = first;
            for (int i = 0; i < total_amount; i++)
            {
                string file = files[i];
                Bitmap bmpSource = new Bitmap(file);
                imageArray[i] = bmpSource;

                last = i;
                int image_height = bmpSource.Height;
                total_height += image_height; //累加高度
                width = width > bmpSource.Width ? width : bmpSource.Width; //取最大宽度

                //再加一张就超过了就保存。
                if (total_height > MAX_HEIGHT)
                {
                    //制作文件名
                    mergeCount++;
                    string filename = buildFileName(mergeCount);
                    last = last - 1;
                    total_height = total_height - image_height;
                    saveImage(imageArray, first, last, width,total_height , image_path + "\\a" + filename + ".jpg");

                    first = i ;
                    last = first;
                    total_height = image_height;
                }
                //如果这张是最后一张图了，
                if (i >= total_amount - 1)
                {
                    mergeCount++;
                    string filename = buildFileName(mergeCount);
                    saveImage(imageArray, first, last, width, total_height, image_path + "\\a" + filename + ".jpg");
                }

                setWorkStatus("完成:" + (i+1) + "/" + total_amount, (int)((i+1) * 100 / total_amount));
            }
            setWorkStatus("合并完成！", 100);
            clearOrBackup(is_backup, files);
        }
        // 生成两个字符长度的文件名
        private string buildFileName(int count)
        {
            string filename;
            if(count<10)
                filename = "0" + count.ToString();
            else
                filename = count.ToString();

            return filename;
        }
        /// <summary>
        /// 备份或者删除
        /// </summary>
        /// <param name="backup">备份标记</param>
        /// <param name="files">文件列表</param>
        private void clearOrBackup(bool backup, string[] files)
        {
            foreach (string file in files)
            {
                //如果选择备份，就复制到bak子目录，否则删除原图。
                if (backup)
                {
                    if (!Directory.Exists(Path.GetDirectoryName(file) + "/bak/"))
                        Directory.CreateDirectory(Path.GetDirectoryName(file) + "/bak/");
                    string new_path = Path.GetDirectoryName(file) + "/bak/" + Path.GetFileName(file);
                    File.Move(file, new_path);
                }
                else
                    File.Delete(file);
            }
        }
           

        /// <summary>
        /// 保存图片
        /// </summary>
        /// <param name="imageArray">图片集</param>
        /// <param name="first">开始图片</param>
        /// <param name="last">最后图片</param>
        /// <param name="width">图片宽度</param>
        /// <param name="height">图片总高度</param>
        /// <param name="filename">保存文件名</param>
        private void saveImage(Bitmap[] imageArray, int first, int last, int width, int height, string filename)
        {
            Bitmap bmpTarget = new Bitmap(width, height);
            Graphics graph = Graphics.FromImage(bmpTarget);
            graph.DrawImage(bmpTarget, width, height);
            int currentHeight = 0;
            for (int i = first; i <=last; i++)
            {
                //拼图
                graph.DrawImage(imageArray[i], 0, currentHeight);
                //拼接改图后，当前高度
                currentHeight += imageArray[i].Height;
                imageArray[i].Dispose();
            }
            var eps = new EncoderParameters(1);
            var ep = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, 75L);
            eps.Param[0] = ep;
            var jpsEncodeer = GetEncoder(ImageFormat.Jpeg);
            bmpTarget.Save(filename, jpsEncodeer, eps);
            bmpTarget.Dispose();
        }
        //获得图像编码信息
        public static ImageCodecInfo GetEncoder(ImageFormat format)
        {
            ImageCodecInfo[] codecs = ImageCodecInfo.GetImageDecoders();
            foreach (ImageCodecInfo codec in codecs)
            {
                if (codec.FormatID == format.Guid)
                    return codec;
            }
            return null;
        }
        public void setWorkStatus(string status, int amount)
        {
            //来设置工作状态，解决多线程下不能设置问题
            try
            {
                if (myForm.InvokeRequired)
                {
                    SetTextCallback d = new SetTextCallback(setWorkStatus);
                    myForm.Invoke(d, new object[] { status, amount });

                }
                else
                {
                    if (status != "")
                    {
                        myForm.slStatus.Text = status;
                    }

                    if (amount != 0)
                    {
                        myForm.statusProgress.Value = amount;
                        if (amount == 100)
                        {
                            myForm.slStatus.Text = "完成";
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                string info = ex.Message + ex.Data;
                setWorkStatus("", 0);

            }

        }

    }
}
